<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Java基本功——Reference - 梦想风暴 - 博客大巴</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="keywords" content="博客中国,中国博客,我的博客,私人日志,博客大巴,图片博客,社会热点,观点,生活,旅行,影像,自由,表达,城客,记录,分享,看法自由报,新媒体,博客研究,播客,BSP,个人门户,免费博客,空间,博客申请,中文博客,Blog,Blogger,网络日志,自媒体,社交网络,小清新,文艺范儿" />
<meta name='description' content='这是一篇一年多之前便已写就的文章，那时，因为很多Java程序员只求追随新生的事物，却连基本的概念都没有，很多讨论中，很明显是基本功不过硬，于是萌生写一个系列文章，讨论Java的基本功，下面便是在这个想法下催生出的第一篇文章。可事实上，真正完成的也只有这一篇。因为未能及时发布，它就被我遗忘在硬盘的角落中。...' />
<link rel='alternate' type='application/rss+xml' title='RSS 2.0' href='http://dreamhead.blogbus.com/index.rdf' />
<link href='http://public.blogbus.com/blogbus/skin_css/sys/50004.css' rel='stylesheet' type='text/css' />
<script>if (top.location != self.location) {top.location=self.location;}</script><script src="http://public.blogbus.com/imgs/jquery.js"></script><link rel="stylesheet" href="http://public.blogbus.com/imgs/picobox/picobox.css" type="text/css"  /><link rel="stylesheet" href="http://public.blogbus.com/imgs/picobox/picobox_beauty/picobox_beauty.css" type="text/css"  /><script type="text/javascript" src="http://public.blogbus.com/imgs/picobox/picobox.js"></script><script type="text/javascript" src="http://public.blogbus.com/imgs/picobox/picobox_beauty/picobox_beauty.js"></script><script type="text/javascript" src="http://cbjs.baidu.com/js/m.js"></script><script type="text/javascript">BAIDU_CLB_preloadSlots("452847","452844");</script><script type="text/javascript" src="http://public.blogbus.com/checkSpam.js"></script><script type="text/javascript">
var content_img_width = 500;
</script></head><body>
<div id="index">
	<div id="container">
		<div id="header">
			<h1 class="blogName"><a href="http://dreamhead.blogbus.com" title="http://dreamhead.blogbus.com">梦想风暴</a></h1>
			<div class="description">一个小程序员的信口开河</div>
			<div class="clear"></div>
		</div>
       <div id="innerContainer">
           <div class="innerTop"></div>
            <div id="outerContent">
                <div id="content">
                    <div class="contentTop"></div>
                        <ul id="posts">
                            <div class="postsTop"></div>
                            <div class="context"><span class="pre"><a href='/logs/1188000.html'>&lt;&lt;&nbsp;&nbsp;由Reflection想到的</a></span> | <span class="top"><a href="http://dreamhead.blogbus.com">首页</a></span> | <span class="next"><a href='/logs/1222792.html'>读《ACM图灵奖》&nbsp;&nbsp;&gt;&gt;</a></span></div>
                            <!--list-->
                            <li>
                                <div class="postHeader">
                                    <h3>2005-05-16</h3>
                                    <h2>Java基本功——Reference</h2>
                                    <div class="tags">Tag：<a href="/tag/大头文章/">大头文章</a> </div>
                                </div>
                                <div class="postBody">
                                    <p class="cc-lisence" style="line-height:180%;">
<a href="http://creativecommons.org/licenses/by/3.0/deed.zh" target="_blank">版权声明</a>：转载时请以超链接形式标明文章原始出处和作者信息及<a
href="http://bangzhuzhongxin.blogbus.com/logs/11205960.html"
target="_blank">本声明</a><br /><a href="http://dreamhead.blogbus.com/logs/1189478.html">http://dreamhead.blogbus.com/logs/1189478.html</a><br /><br />
</p><p>这是一篇一年多之前便已写就的文章，那时，因为很多Java程序员只求追随新生的事物，却连基本的概念都没有，很多讨论中，很明显是基本功不过硬，于是萌生写一个系列文章，讨论Java的基本功，下面便是在这个想法下催生出的第一篇文章。可事实上，真正完成的也只有这一篇。因为未能及时发布，它就被我遗忘在硬盘的角落中。今天，JavaEye上关<a href="http://forum.javaeye.com/viewtopic.php?t=12961">于Java传值还是传引用</a>的论战让我记起了自己曾经写过的这篇文章，愿与大家共享。</p><p><strong><font size="5">Java基本功——Reference</font></strong></p><p>有这样一种说法，如今争锋于IT战场的两大势力，MS一族偏重于底层实现，Java一族偏重于系统架构。说法根据无从考证，但从两大势力各自的社区力量和图书市场已有佳作不难看出，此说法不虚。于是，事情的另一面让人忽略了。<br />偏巧，我是一个喜欢探究底层实现的Java程序员，虽然我的喜好并非纯正咖啡，剑走偏锋却别是一番风味。</p><p><font size="4"><strong><font size="5">Reference</font></strong><br /></font>Java世界泰山北斗级大作《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中，reference是一切谜题的根源，所有的故事都是从这里开始的。</p><p><strong><font face="楷体_GB2312" size="4">Reference是什么？</font><br /></strong>如果你和我一样在进入Java世界之前曾经浪迹于C/C++世界，就一定不会对指针陌生。谈到指针，往日种种不堪回首的经历一下子涌上心头，这里不是抱怨的地方，让我们暂时忘记指针的痛苦，回忆一下最初接触指针的甜蜜吧！还记得你看过的教科书中，如何讲解指针吗？留在我印象中的一种说法是，指针就是地址，如同门牌号码一样，有了地址，你可以轻而易举找到一个人家，而不必费尽心力的大海捞针。<br />C++登上历史舞台，reference也随之而来，容我问个小问题，指针和reference区别何在？我的答案来自于在C++世界享誉盛名的《More Effective C++》。</p><ol><li>没有null reference。</li><li>reference必须有初值。</li><li>使用reference要比使用指针效率高。因为reference不需要测试其有效性。</li><li>指针可以重新赋值，而reference总是指向它最初获得的对象</li></ol><p><strong>设计选择：</strong><br />当你指向你需要指向的某个东西，而且绝不会改指向其它东西，或是当你实作一个运算符而其语法需要无法有指针达成，你就应该选择reference。其它任何时候，请采用指针。</p><p>这和Java有什么关系？<br />初学Java，鉴于reference的名称，我毫不犹豫的将它和C++中的reference等同起来。不过，我错了。在Java中，reference可以随心所欲的赋值置空，对比一下上面列出的差异，就不难发现，Java的reference如果要与C/C++对应，它不过是一个穿着reference外衣的指针而已。<br />于是，所有关于C中关于指针的理解方式，可以照搬到Java中，简而言之，reference就是一个地址。我们可以把它想象成一个把手，抓住它，就抓住了我们想要操纵的数据。如同掌握C的关键在于掌握指针，探索Java的钥匙就是reference。</p><p><font face="楷体_GB2312" size="4">一段小程序</font><br />我知道，太多的文字总是令人犯困，那就来段代码吧！<br /><font face="Arial">public class ReferenceTricks {<br />  public static void main(String[] args) {<br />    ReferenceTricks r = new ReferenceTricks();<br />    // reset integer<br />    r.i = 0;<br />    System.out.println(&quot;Before changeInteger:&quot; + r.i);<br />    changeInteger(r);<br />    System.out.println(&quot;After changeInteger:&quot; + r.i);</font></p><p><font face="Arial">    // just for format<br />    System.out.println();<br />  <br />    // reset integer<br />    r.i = 0;<br />    System.out.println(&quot;Before changeReference:&quot; + r.i);<br />    changeReference(r);<br />    System.out.println(&quot;After changeReference:&quot; + r.i);<br />  }</font></p><p><font face="Arial">  private static void changeReference(ReferenceTricks r) {<br />   r = new ReferenceTricks();<br />   r.i = 5;<br />   System.out.println(&quot;In changeReference: &quot; + r.i);<br />  }</font></p><p><font face="Arial">  private static void changeInteger(ReferenceTricks r) {<br />   r.i = 5;<br />   System.out.println(&quot;In changeInteger:&quot; + r.i);<br />  }</font></p><p><font face="Arial">  public int i;<br />}<br /></font><br />对不起，我知道，把一个字段设成public是一种不好的编码习惯，这里只是为了说明问题。<br />如果你有兴趣自己运行一下这个程序，我等你！</p><p>OK，你已经运行过了吗？结果如何？是否如你预期？下面是我在自己的机器上运行的结果：<br /><font face="Arial">Before changeInteger:0<br />In changeInteger:5<br />After changeInteger:5</font></p><p><font face="Arial">Before changeReference:0<br />In changeReference: 5<br />After changeReference:0</font><br />这里，我们关注的是两个change——changeReference和changeInteger。从输出的内容中，我们可以看出，两个方法在调用前和调用中完全一样，差异出现在调用后的结果。</p><p><font face="楷体_GB2312" size="4">糊涂的讲解</font><br />先让我们来分析一下changeInteger的行为。<br />前面说过了，Java中的reference就是一个地址，它指向了一个内存空间，这个空间存放着一个对象的相关信息。这里我们暂时不去关心这个内存具体如何排布，只要知道，通过地址，我们可以找到r这个对象的i字段，然后我们给它赋成5。既然这个字段的内容得到了修改，从函数中返回之后，它自然就是改动后的结果了，所以调用之后，r对象的i字段依然是5。下图展示了changeInteger调用前后内存变化。</p><p><font face="Times New Roman"><font face="Courier New">     Reference +--------+                Reference +--------+<br />    ----------&gt;| i = 0  |               ----------&gt;| i = 5  |<br />               |--------|                          |--------|<br />               | Memory |                          | Memory |<br />               |        |                          |        | <br />               |        |                          |        |<br />               +--------+                          +--------+</font></font></p><p><font face="Times New Roman"><font face="Courier New">    调用changeInteger之前               调用changeInteger之后</font></font></p><p>让我们把目光转向changeReference。<br />从代码上，我们可以看出，同changeInteger之间的差别仅仅在于多了这么一句。<br />r = new ReferenceTricks();<br />这条语句的作用是分配一块新的内存，然后将r指向它。<br />执行完这条语句，r就不再是原来的r，但它依然是一个ReferenceTricks的对象，所以我们依然可以对这个r的i字段赋值。到此为止，一切都是那么自然。</p><p><font face="Courier New">     Reference +--------+                          +--------+<br />    ----------&gt;| i = 0  |                          | i = 0  |<br />               |--------|                          |--------|<br />               | Memory |                          | Memory |<br />               |        |                Reference |--------| <br />               |        |               ----------&gt;| i = 5  |<br />               +--------+                          +--------+</font></p><p><font face="Courier New">    调用changeReference之前              调用changeReference之后</font></p><p>顺着这个思路继续下去的话，执行完changeReference，输出的r的i字段，那么应该是应该是新内存中的i，所以应该是5。至于那块被我们抛弃的内存，Java的GC功能自然会替我们善后的。<br />事与愿违。<br />实际的结果我们已经看到了，输出的是0。<br />肯定哪个地方错了，究竟是哪个地方呢？</p><p><font face="楷体_GB2312" size="4">参数传递的秘密</font><br />知道方法参数如何传递吗？<br />记得刚开始学编程那会儿，老师教导，所谓参数，有形式参数和实际参数之分，参数列表中写的那些东西都叫形式参数，在实际调用的时候，它们会被实际参数所替代。<br />编译程序不可能知道每次调用的实际参数都是什么，于是写编译器的高手就出个办法，让实际参数按照一定顺序放到一个大家都可以找得到的地方，以此作为方法调用的一种约定。所谓“没有规矩，不成方圆”，有了这个规矩，大家协作起来就容易多了。这个公共数据区，现在编译器的选择通常是“栈”，而所谓的顺序就是形式参数声明的顺序。<br />显然，程序运行的过程中，作为实际参数的变量可能遍布于内存的各个位置，而并不一定要老老实实的呆在栈里。为了守“规矩”，程序只好将变量复制一份到栈中，也就是通常所说的将参数压入栈中。<br />打起精神，谜底就要揭晓了。<br />我刚才说什么来着？将变量复制一份到栈中，没错，“复制”！<br />这就是所谓的值传递。<br />C语言的旷世经典《The C Programming Language》开篇的第一章中，谈到实际参数时说，“在C中，所有函数的实际参数都是传‘值’的”。<br />马上会有人站出来，“错了，还有传地址，比如以指针传递就是传地址”。<br />不错，传指针就是传地址。在把指针视为地址的时候，是否考虑过这样一个问题，它也是一个变量。前面的讨论中说过了，参数传递必须要把参数压入栈中，作为地址的指针也不例外。所以，必须把这个指针也复制一份。函数中对于指针操作实际上是对于这个指针副本的操作。<br />Java的reference等于C的指针。所以，在Java的方法调用中，reference也要复制一份压入堆栈。在方法中对reference的操作就是对这个reference副本的操作。<br />谜底揭晓<br />好，让我们回到最初的问题上。<br />在changeReference中对于reference的赋值实际上是对这个reference的副本进行赋值，而对于reference的本尊没有产生丝毫的影响。<br />回到调用点，本尊醒来，它并不知道自己睡去的这段时间内发生过什么，所以只好当作什么都没发生过一般。就这样，副本消失了，在方法中对它的修改也就烟消云散了。<br /> <br />也许你会问出这样的问题，“听了你的解释，我反而对changeInteger感到迷惑了，既然是对于副本的操作，为什么changeInteger可以运作正常？”<br />呵呵，很有趣的大脑短路现象。<br />好，那我就用前面的说法解释一下changeInteger的运作。<br />所谓复制，其结果必然是副本完全等同于本尊。reference复制的结果必然是两个reference指向同一块内存空间。<br />虽然在方法中对于副本的操作并不会影响到本尊，但对内存空间的修改确实实实在在的。<br />回到调用点，虽然本尊依然不知道曾经发生过的一切，但它按照原来的方式访问内存的时候，取到的确是经过方法修改之后的内容。<br />于是方法可以把自己的影响扩展到方法之外。<br /> <br /><font face="楷体_GB2312" size="4">多说几句</font><br />这个问题起源于我对C/C++中同样问题的思考。同C/C++相比，在changeReference中对reference赋值可能并不会造成什么很严重的后果，而在C/C++中，这么做却会造成臭名昭著的“内存泄漏”，根本的原因在于Java拥有了可爱的GC功能。即便这样，我仍不推荐使用这种的手法，毕竟GC已经很忙了，我们怎么好意思再麻烦人家。<br />在C/C++中，这个问题还可以继续引申。既然在函数中对于指针直接赋值行不通，那么如何在函数中修改指针呢？答案很简单，指针的指针，也就是把原来的指针看作一个普通的数据，把一个指向它的指针传到函数中就可以了。<br />同样的问题到了Java中就没有那么美妙的解决方案了，因为Java中可没有reference的reference这样的语法。可能的变通就是将reference进行封装成类。至于值不值，公道自在人心。</p><p><font face="楷体_GB2312" size="4">参考文献<br /></font>1 《Thinking in Java》<br />2 《More Effective C++》<br />3 《The C Programming Language》</p><div class="relpost"><br/><h3>历史上的今天：</h3><div><a href='http://dreamhead.blogbus.com/logs/63646898.html'>争论TDD</a> 2010-05-16</div><div><a href='http://dreamhead.blogbus.com/logs/2485510.html'>做好该做的事</a> 2006-05-16</div></div>
                                    <div class="clear"></div>
                                </div>
                                <div class="tb_url">引用地址：<input type="text" value="http://www.blogbus.com/public/tb.php/4212/1189478/89f5c13acadec559d69469b7e62f83c5"/></div>
                                <div class="postFooter">
                                    <div class="menubar"><span class="author"><a href="http://home.blogbus.com/profile/dreamhead">dreamhead</a></span> 发表于<span class="time">18:37</span> | <a href='http://blog.home.blogbus.com/4212/posts/1189478/form' class='edit'>编辑</a> | <a href='javascript:;' class='dig' target='_blank' onclick="share_click('share_cc224c3d1058482e8f9d3187601f9b5e'); Picobox.showIFrameBox('分享文章','http://app.home.blogbus.com/share?url=http%3A%2F%2Fdreamhead.blogbus.com%2Flogs%2F1189478.html&from=blogbus&back=http%3A%2F%2Fdreamhead.blogbus.com',{width:400,height:260}); return false;">分享<span id='share_cc224c3d1058482e8f9d3187601f9b5e'>　0</span></a></div>
                                </div>
                            </li>
                            <!--/list-->
                            <div class="postsBottom"></div>
                        </ul><a name="cmt"></a><ul id="comments"><h2>评论</h2>
<li><div class='cmtBody'>非常受用的文章，真正在这个知识点上受到了醍醐灌顶的感觉！</div>

<div class='menubar'><span class='author'>jackaniu | </span> 发表于<span class='time'>2010-04-16 18:03:50</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=69670372', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>大师傅吧手到病除 设备擦设备敌百虫撒播后，上午说大话少年板瓦；</div>

<div class='menubar'><span class='author'><a href="http://360"  rel="nofollow" target="_blank"> ncxjAB Csn ch</a> | </span> 发表于<span class='time'>2006-08-03 15:01:48</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=3472059', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>例子不好，在ChangeReference()中的r，基本上没有被使用</div>

<div class='menubar'><span class='author'>flj | </span> 发表于<span class='time'>2006-04-03 11:32:01</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=2609978', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>reference 也可以改变指向的对象</div>
<div class="reCmtBody"><div><span class="author">dreamhead</span>回复<span>elathen</span>说：</div><div class="content">这是Java与C++ reference的差别。</div><div class="time">2005-06-01 10:13:54</div></div>
<div class='menubar'><span class='author'>elathen | </span> 发表于<span class='time'>2005-05-31 20:59:38</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1676827', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>楼主blog的定位有点问题，是与人分享编程思想还是普及java教育？定位不明确岂不浪费别人的时间</div>
<div class="reCmtBody"><div><span class="author">dreamhead</span>回复<span>yally_l</span>说：</div><div class="content">我并不觉得有什么矛盾的，为什么我的思想就不能是简单的内容呢？我并不把自己放在高手的行列中，所以有些想法简单了也很正常。如果这些内容恰好可以帮助别人，何乐不为呢？事实上，正是因为有些朋友对这个问题不清楚，我倒是觉得这篇文章是有价值的。<br />
<br />
与大家分享这些内容是为了让自己快乐，别把我看得很高，那会让感觉我很累的。</div><div class="time">2005-05-24 20:50:11</div></div>
<div class='menubar'><span class='author'>yally_l | </span> 发表于<span class='time'>2005-05-23 14:38:21</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1645862', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>不明白为什麽出现这样基础的问题，java已经说明了自己的立场＝所有的参数都是按值传递！引用本身就是c/c++中的指针概念，将地址copy给参数不就理解了，至于写这样一打大段文章吗？</div>
<div class="reCmtBody"><div><span class="author">dreamhead</span>回复<span>Killvin</span>说：</div><div class="content">如果我没有看到很多朋友讨论这种问题，我可能也不会把这篇文章贴出来。对于已经越过初级阶段的你，也许它的意义没有那么大，但是对于初入门的朋友，它还是有一些价值的。</div><div class="time">2005-05-22 20:28:47</div></div>
<div class='menubar'><span class='author'>Killvin | </span> 发表于<span class='time'>2005-05-21 18:50:21</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1642386', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>从这篇开始，读了你的几篇文章，促使我想了许多更本质的问题。对于刚入行的自己，需要一种清醒，感谢你给了我需要的东西。你是我的榜样</div>
<div class="reCmtBody"><div><span class="author">dreamhead</span>回复<span>yic</span>说：</div><div class="content">能让你思考是对我付出最大的肯定，让我们一起努力！</div><div class="time">2005-05-22 20:25:59</div></div>
<div class='menubar'><span class='author'><a href="http://dotnet.mblogger.cn/yicone/"  rel="nofollow" target="_blank">yic</a> | </span> 发表于<span class='time'>2005-05-20 16:22:53</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1640231', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'> 恩 我觉得也可以这样理解, 函数参数,也就是 private static void changeReference(ReferenceTricks r) <br /><br />
  这个r 应该是在内存中独立开辟出来的一个reference对象. 在changeInteger因为这个r 和 外面那个是指向同一块内存区域,所以changeInteger函数内的改变会影响到外面的那个r对象;<br /><br />
  但是在changeReference函数中的这个r ,你用 new ReferenceTricks() 把这个r指向了一个新的对象,所以你怎么在函数里面改变 都是不会影响外面的!!!<br /><br />
  我是这么理解这段程序的,因为我C 的那块忘记完了,可能楼主的解释才是真正的本质情况, 而我的只是一种理解方式, 还需要向楼主学习! 希望能得到楼主的联系方式!! </div>
<div class="reCmtBody"><div><span class="author">dreamhead</span>回复<span>zhouysh</span>说：</div><div class="content">我的联系方式就在blog上，把鼠标放在“dreamhead”上就可以看到了。^_^</div><div class="time">2005-05-19 10:53:13</div></div>
<div class='menubar'><span class='author'>zhouysh | </span> 发表于<span class='time'>2005-05-19 10:21:29</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1637528', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li>
<li><div class='cmtBody'>品味这篇文章，让我想到另一个问题，除去原始类型，C++与JAVA在对对象的内存分配上有一个非常大的区别： C++可以把一个对象放在栈上，比如：<br /><br />
  class   A ;<br /><br />
     A a ;<br /><br />
对象的实体是位于栈上的， 而JAVA似乎只能让对象实体位于堆上，对象引用留在栈上，当退出栈时，引用失效，对象实体就可以由GC收集了，如果C++要想得到位于堆上的对象，只有用NEW就可以了，但是没有语言层次的回收机制；当然用智能指针包装的除外。<br /><br />
</div>

<div class='menubar'><span class='author'>chenxiujie | </span> 发表于<span class='time'>2005-05-17 15:36:49</span>
<span>[<a href="#" onclick="Picobox.showIFrameBox('回复评论', 'http://blog.home.blogbus.com/4212/comments/1189478/reply?cmid=1634413', {width:310, height:200});return false;" rel="facebox">回复</a>]</span></div></li></ul>
<div id="commentForm"></div>
<script type="text/javascript" src="http://blog.home.blogbus.com/front/4212/comments/1189478/cmt_form"></script>
<script type='text/javascript'>var post_ids='1189478';</script><script type='text/javascript' src='http://app.home.blogbus.com/share/number?id=1189478'></script><script>function share_click(id){var num = parseInt(document.getElementById(id).innerHTML);	num++;document.getElementById(id).innerHTML= ' '+num;}</script><script type='text/javascript' src='http://public.blogbus.com/blogbus/skin/common/helper1.js?v1024'></script>
                    <div class="contentBottom"></div>                    
                </div>
            </div>
            <div id="outerSidebar">
                <div id="sidebar">
                    <div class="sideTop"></div>
                    <div id="search" class="module">
	<div class="modTop"></div>
	<h2>搜索</h2>
	<div class="modBody">
	    <form action="http://www.google.com/cse" id="cse-search-box" target="_blank">
		<input type="hidden" name="cx" value="000579218792228101724:tvuzu9tzfs0" />
		<input type="hidden" name="ie" value="UTF-8" />
		<input type="text" name="q" class="textField" />
		<input type="submit" class="button" value="搜索" />
		<div class="clear"></div>
	    </form>
	</div>
	<div class="modBottom"></div>
</div><div id="nPosts" class="module">
	<div class="modTop"></div>
	<h2>最新日志</h2>
	<div class="modBody">
		<ul><li><a href='/logs/231514183.html'>杂谈时间管理</a></li>
<li><a href='/logs/230834007.html'>Fedex Day</a></li>
<li><a href='/logs/230244140.html'>Jackson雕虫技（二）</a></li>
<li><a href='/logs/230244031.html'>Jackson雕虫技（一）</a></li>
<li><a href='/logs/229714206.html'>实践中的重构</a></li>
<li><a href='/logs/229382281.html'>在成都Open Party讲Moco</a></li>
<li><a href='/logs/229301247.html'>Hello，Moco（番外篇之前端开发）</a></li>
<li><a href='/logs/228721904.html'>一篇Java函数式编程文章的讨论</a></li>
<li><a href='/logs/227427912.html'>你应该更新的Java知识之构建工具</a></li>
<li><a href='/logs/227268386.html'>Hello，Travis CI</a></li>
</ul>
		<div class="more"><a href="/logs/">全部日志>></a></div>
	</div>
	<div class="modBottom"></div>
</div><div id="nComments" class="module">
	<div class="modTop"></div>
	<h2>最新评论</h2>
	<div class="modBody">
		<ul><li><span class='author'>Benwei1988</span>：<a href='/logs/229714206.html#cmt'>重写和重构之间如何划分呢，假设，我以前写的代码比较的过程...</a></li><li><span class='author'><a href="http://greatghoul.blogbus.com" target="_blank">greatghoul</a></span>：<a href='/logs/229714206.html#cmt'>上交一位 thoughworks 的朋友分享了他们公司的...</a></li><li><span class='author'><a href="http://ilstar.blogbus.com" target="_blank">子非鱼</a></span>：<a href='/logs/229714206.html#cmt'>以前写代码总是想一次性写的更好一些，现在慢慢的把心态转过...</a></li><li><span class='author'>greatghoul</span>：<a href='/logs/229714206.html#cmt'>对于一些 ajax 交互比较复杂的页面，如何写测试用例呢...</a></li><li><span class='author'>kingzzm</span>：<a href='/logs/226738756.html#cmt'>只有SLF4J和Logback没用过，还可以加个使用ID...</a></li><li><span class='author'>niufish</span>：<a href='/logs/226738756.html#cmt'>都收了，多谢</a></li><li><span class='author'>Tony Bai</span>：<a href='/logs/226604152.html#cmt'>郑大大2012收获蛮多的阿。“教书匠”的体验让人羡慕啊，...</a></li><li><span class='author'><a href="http://libc.blogbus.com" target="_blank">greatgarlic</a></span>：<a href='/logs/226077776.html#cmt'>你好，我看了你写的这个很惊讶

“作为一个新时代自动...</a></li><li><span class='author'><a href="http://nethibernate.blogbus.com" target="_blank">胖虫</a></span>：<a href='/logs/223812564.html#cmt'>现在我最头疼的就是英文书。尤其是技术类的，有的时候想直接...</a></li><li><span class='author'><a href="http://ilstar.blogbus.com" target="_blank">子非鱼</a></span>：<a href='/logs/225238435.html#cmt'>TW真是一个绝好的平台，不仅能够锻炼敏锐的思考能力，良好...</a></li></ul>
	</div>
	<div class="modBottom"></div>
</div>
<div id='custom'><script type="text/javascript" src="http://www.douban.com/service/badge/dreamhead/?show=collection&amp;n=8&amp;columns=2&amp;cat=book" ></script>

<iframe id="sina_widget_2192241300" style="width:100%; height:500px;" frameborder="0" scrolling="no" src="http://v.t.sina.com.cn/widget/widget_blog.php?uid=2192241300&height=500&skin=wd_02&showpic=1"></iframe></div>
                    <div id="meta" class="module">
                        <div class="modTop"></div>
                            <div class="modBody">
                                <ul>
 <li class="subscribe" style="line-height:180%;"><div><a href="http://dreamhead.blogbus.com/index.rdf"><img src="http://www.blogbus.com/images/site-v3/rss.gif" alt="RSS" /></a> <a href="http://bangzhuzhongxin.blogbus.com/logs/5452786.html" target="_blank">什么是RSS？</a></div><div class="inezha" style="margin:.5em 0"><a href="http://inezha.com/add2?hid=2320&url=http://dreamhead.blogbus.com/index.rdf" title="此博客内容更新用IM提醒我" target="_blank"><img src="http://public.blogbus.com/rss/anothr.gif" alt="用IM提醒我内容更新"/></a></div><div class="qqmail" style="margin:.5em 0"><a href="http://mail.qq.com/cgi-bin/feed?u=http://dreamhead.blogbus.com/index.rdf" title="订阅到QQ邮箱" target="_blank"><img src="http://public.blogbus.com/rss/qqmail.png" alt="订阅到QQ邮箱"/></a></div><div class="xiangguo" style="margin:.5em 0"><a href="http://www.xianguo.com/subscribe.php?url=http://dreamhead.blogbus.com/index.rdf" title="订阅到鲜果阅读器" target="_blank"><img src="http://public.blogbus.com/rss/xianguo.png" alt="订阅到鲜果阅读器"/></a></div><div class="g-reader" style ="margin:.5em 0"><a href="http://fusion.google.com/add?feedurl=http://dreamhead.blogbus.com/index.rdf" title="订阅到Google阅读器" target="_blank"><img src="http://public.blogbus.com/rss/google.png" alt="订阅到Google阅读器"/></a></div><div class="zhuaxia" style ="margin:.5em 0"><a href="http://www.zhuaxia.com/add_channel.php?url=http://dreamhead.blogbus.com/index.rdf" title="订阅到抓虾阅读器" target="_blank"><img src="http://public.blogbus.com/rss/zhuaxia.png" alt="订阅到抓虾阅读器"/></a></div></li>
                                   <li class="poweredBy">
                                        <a href="http://www.blogbus.com/" target="_blank"><img src="http://www.blogbus.com/images/site-v3/link_blogbus.gif" alt="博客大巴" /></a><div><a href="http://bangzhuzhongxin.blogbus.com" target="_blank" title="博客大巴使用指南">博客大巴使用指南</a></div><div><a href="http://www.blogbus.com/skin/" target="_blank" title="博客大巴模板中心">博客大巴模板中心</a></div><div><a href="http://passport.blogbus.com/register_form" target="_blank" title="免费注册博客大巴">免费注册博客大巴</a></div><div><a href="http://banjia.blogbus.com/" target="_blank" title="一键博客搬家工具">一键博客搬家工具</a></div><div><a href="http://www.icity.cn/" target="_blank" title="中文互动杂志城客">中文互动杂志城客</a></div>
                                    </li>
                                </ul>
                            </div>
                            <div class="modBottom"></div>
                        </div>
                    <div class="sideBottom"></div>
                </div>
            </div>
            <div class="innerBottom"></div>
        </div>
		<div class="clear"></div>
		<div id="footer">
			<div class="copyright">Copyright &copy; 2002-2013 BlogBus.com, All Rights Reserved. <a href="http://www.blogbus.com" target="_blank">博客大巴</a> 版权所有</div>
		</div>
	</div>
</div></body></html><script type="text/javascript" src="http://public.blogbus.com/blogbus/skin/common/helper1.js?v1023"></script><script type="text/javascript">
        var gaJsHost = (("https:" == document.location.protocol)?"https://ssl." : "http://www.");
        document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
        </script>
        <script type="text/javascript">
        var pageTracker = _gat._getTracker("UA-2120146-1");
        pageTracker._setDomainName(".blogbus.com");
        pageTracker._addOrganic("baidu","word");
        pageTracker._addOrganic("baidu","wd");
        pageTracker._addOrganic("soso","w");
        pageTracker._addOrganic("vnet","kw");
        pageTracker._initData();
        pageTracker._trackPageview();
	</script><div style="display:none;"><script type="text/javascript">
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F8452dbf205b0f6608661b0fdea22c741' type='text/javascript'%3E%3C/script%3E"));
</script></div><script type="text/javascript" src="http://counter.blogbus.com/counter.js.php"></script>